package com.analyse.stock.utils;

import com.analyse.stock.model.StockKlineDailyModel;
import org.ta4j.core.*;
import org.ta4j.core.criteria.pnl.GrossReturnCriterion;
import org.ta4j.core.indicators.SMAIndicator;
import org.ta4j.core.indicators.helpers.ClosePriceIndicator;
import org.ta4j.core.num.Num;
import org.ta4j.core.rules.CrossedDownIndicatorRule;
import org.ta4j.core.rules.CrossedUpIndicatorRule;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;

public class TradingStrategyUtil {

    /**
     * 创建模拟时间序列
     * @return 时间序列
     */
    private static BarSeries createSeries(List<StockKlineDailyModel> stockData, String seriesName) {
        // 构建时间序列
        BarSeries series = new BaseBarSeriesBuilder().withName(seriesName).build();
        for(StockKlineDailyModel model : stockData){
            // 将java.util.Date转换为java.time.ZonedDateTime
            ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(model.getTradeDate().toInstant(), ZoneId.of("Asia/Shanghai"));
            series.addBar(zonedDateTime, model.getOpenPrice(),
                    model.getHighPrice(), model.getLowerPrice(), model.getPrice(), model.getTradeVolume());
        }
        return series;
    }

    public static void execSMAStrategy(List<StockKlineDailyModel> stockData){
        // 构建时间序列
        BarSeries series = createSeries(stockData,"SMA-Series");

        // 创建指标：短期均线（10 日）和长期均线（50 日）
        ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
        SMAIndicator shortSma = new SMAIndicator(closePrice, 10);
        SMAIndicator longSma = new SMAIndicator(closePrice, 50);

        // 定义买入规则：短期均线上穿长期均线
        Rule buyRule = new CrossedUpIndicatorRule(shortSma, longSma);

        // 定义卖出规则（可选）：短期均线下穿长期均线
        Rule sellRule = new CrossedDownIndicatorRule(shortSma, longSma);

        // 创建策略
        Strategy strategy = new BaseStrategy(buyRule, sellRule);

        // 回测策略
        BarSeriesManager seriesManager = new BarSeriesManager(series);
        TradingRecord tradingRecord = seriesManager.run(strategy);

        // 输出交易信号
        System.out.println("买入/卖出信号：");
        tradingRecord.getPositions().forEach(trade -> {
            System.out.println(trade.getEntry().getType() + " 于索引：" + trade.getEntry().getIndex());
            System.out.println(trade.getExit().getType() + " 于索引：" + trade.getExit().getIndex());
        });

        // 计算回测绩效 - 使用 GrossReturnCriterion
        GrossReturnCriterion profitCriterion = new GrossReturnCriterion();
        Num totalProfit = profitCriterion.calculate(series, tradingRecord);
        System.out.println("总收益: " + totalProfit);

        // 计算买入并持有策略收益
        //HoldReturnCriterion buyAndHoldCriterion = new BuyAndHoldReturnCriterion();
        //Num buyAndHoldProfit = buyAndHoldCriterion.calculate(series, tradingRecord);
        //System.out.println("买入并持有收益: " + buyAndHoldProfit);
    }
}
